package com.ykg.interceptor;


import com.ykg.annotation.PassToken;
import com.ykg.enums.ResultEnum;
import com.ykg.exception.CommonException;
import com.ykg.mapper.CompanyUserMapper;
import com.ykg.mapper.OwnerMapper;
import com.ykg.pojo.CompanyUser;
import com.ykg.pojo.Owner;
import com.ykg.service.ICuserService;
import com.ykg.service.IOwnerService;
import com.ykg.util.CacheUtil;
import com.ykg.util.JwtUtil;
import com.ykg.util.LocalUtil;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

@Component
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    JwtUtil jwtUtil;

    @Autowired
    private CompanyUserMapper companyUserMapper;

    @Autowired
    private OwnerMapper ownerMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {


        Optional<ScopeLevel> scopeLevel = this.getScopeLevel(handler);

        // 如果是方法上的注解
        if (handler instanceof HandlerMethod) {
            // 判断有没有@PassToken
            Method method = ((HandlerMethod) handler).getMethod();
            if (method.isAnnotationPresent(PassToken.class)) {
                // 如果有则跳过验证
                return true;
            }
            // 如果没有则进行token验证
            String token = request.getHeader(jwtUtil.getHeader());
            if (StringUtils.isBlank(token)) {
                // 如果不是在header中 判断是否在get方法的参数中
                token = request.getParameter(jwtUtil.getHeader());
            }
            // 如果都不在抛出异常
            if (StringUtils.isBlank(token)) {
                throw new CommonException(ResultEnum.TOKEN_ERROR);
            }
            // 验证token有效时间
            Claims claims = jwtUtil.getClaimByToken(token);
            if (claims == null || jwtUtil.isTokenExpired(claims.getExpiration())) {
                throw new CommonException(ResultEnum.TOKEN_ERROR);
            }

            // 验证是否和缓存中的一致
            String tokenInCache = CacheUtil.get(claims.getSubject());
            if (!token.equals(tokenInCache)) {
                throw new CommonException(ResultEnum.TOKEN_ERROR);
            }

            boolean vali = hasPermission(scopeLevel.get(),claims.getSubject());
            if(!vali){
                throw new CommonException(ResultEnum.TYPE_ERROR);
            }
            // 将userId设置到threadLocal里边
            LocalUtil.addId(claims.getSubject());
        }
        return true;
    }
    /**
     * TODO
     * 将用户id在数据库查询其身份标识，再与其请求的接口要求的身份标识相匹配
     * @params：
     @param scopeLevel
      * @param userId
     * @return {@link boolean}
     * @Author: laobian
     * @Date: 10:17 2021/6/24
     */
    private boolean hasPermission(ScopeLevel scopeLevel,String userId) {

        Integer level = scopeLevel.value();
        int scope = 0;
        String identify = userId.substring(0,1);
        Long id= Long.parseLong(userId.substring(1));
        System.out.println(id+identify);
         if(identify.equals("c")){
            scope = companyUserMapper.findById(id).getIdenfity();
        }else {
           scope= ownerMapper.findOwnerById(id).getIdenfity();
        }
        if (level != scope) {
            return false;
        }
        return true;
    }




    private Optional<ScopeLevel> getScopeLevel(Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            ScopeLevel scopeLevel = handlerMethod.getMethod().getAnnotation(ScopeLevel.class);
            if (scopeLevel == null) {
                return Optional.empty();
            }
            return Optional.of(scopeLevel);
        }
        return Optional.empty();
    }


}
